package websocket

import (
	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/os/gtime"

	"websocket/lib/snowflake"
)

type MessageHandleFunc func(s *Session, m *MessageReq) // 消息处理函数
type MessageHandler struct {                           // 消息处理对象
	Func         MessageHandleFunc // 消息处理函数
	SessionLevel SessionLevel      // 需要的权限等级
}

// MessageReq 请求消息
type MessageReq struct {
	Id       string        // 消息id
	Opcode   MessageOpcode // 操作码
	Data     *gjson.Json   // 解析后的参数
	Original string        // 原始字符串
	Time     *gtime.Time   // 收到消息的时间
}

// MessageResData 回复消息
type MessageResData interface{}
type MessageFromInfo struct { // 消息来源
	Type uint8       `json:"type"` // 消息来源类型
	Info interface{} `json:"info,omitempty"`
}
type MessageRes struct {
	Id     string           `json:"id"` // 消息id
	Opcode MessageOpcode    `json:"a"`  // 操作码
	Data   MessageResData   `json:"d"`  // 请求消息解析后的数据，或者回复消息的数据
	From   *MessageFromInfo `json:"f"`  // 回复消息的来源
}

const (
	FromTypeSession = iota + 1 // 未授权的用户发送
	FromTypeUser               // 授权用户发送
	FromTypeSystem             // 系统发送
)

var (
	snowflakeNode = snowflake.NewNode(`websocket.message`) // 消息id使用单独的生成器
)

// NewOpenMessage 开启链接消息
func NewOpenMessage(r *ghttp.Request, s *Session) *MessageReq {
	return &MessageReq{
		Id:     snowflakeNode.Id(),
		Opcode: OpCommonConnOpen,
		Time:   gtime.Now(),
	}
}

// NewCloseMessage 关闭连接消息
func NewCloseMessage(r *ghttp.Request, s *Session) *MessageReq {
	return &MessageReq{
		Id:     snowflakeNode.Id(),
		Opcode: OpCommonConnClose,
		Time:   gtime.Now(),
		Data:   gjson.New(nil),
	}
}

// NewReqMessage message消息
func NewReqMessage(msg []byte) (*MessageReq, error) {
	json, err := gjson.DecodeToJson(msg)
	if err != nil {
		return nil, err
	}

	return &MessageReq{
		Id:       snowflakeNode.Id(),
		Opcode:   MessageOpcode(json.GetUint16(`a`)),
		Original: string(msg),
		Data:     json.GetJson(`d`),
		Time:     gtime.Now(),
	}, nil
}

// NewResMessage 回复消息
func NewResMessage(opcode MessageOpcode, from *MessageFromInfo, data ...MessageResData) *MessageRes {
	message := &MessageRes{
		Id:     snowflakeNode.Id(),
		Opcode: opcode,
		From:   from,
	}
	if len(data) == 1 {
		message.Data = data[0]
	} else {
		message.Data = data
	}
	return message
}

// NewResMessageBySession 用户发送的消息
func NewResMessageBySession(opcode MessageOpcode, session *Session, data ...MessageResData) *MessageRes {
	var from *MessageFromInfo
	if session.User != nil {
		from = &MessageFromInfo{Type: FromTypeUser, Info: session.User}
	} else {
		from = &MessageFromInfo{Type: FromTypeSession, Info: session}
	}
	return NewResMessage(opcode, from, data...)
}

// NewResMessageBySys 系统消息
func NewResMessageBySys(opcode MessageOpcode, data ...MessageResData) *MessageRes {
	from := &MessageFromInfo{Type: FromTypeSystem}
	return NewResMessage(opcode, from, data...)
}
